#pragma once 

#include <string>
#include <cstdint>
#include <memory>
#include <cstring> 


namespace tmms
{
    namespace mmedia
    {
        enum 
        {  
            KPacketTypeVideo = 1,
            KPacketTypeAudio = 2,
            KPacketTypeMeta = 4,
            KPacketTypeMeta3 = 8,
            KFrameTypeKeyFrame = 16,
            KFrameTypeIDR = 32,
            KPacketTypeUnknowed = 255,
        };

        class Packet;
        using PacketPtr = std::shared_ptr<Packet>;

//改变对齐方式
#pragma pack(push) //改变对齐方式
#pragma pack(1) //推一个字节进去
        class Packet
        {
        private:
            int32_t type_{KPacketTyepUnknowed};
            uint32_t size_{0};
            uint32_t index_{-1};
            uint64_t timestamp_{0};
            uint32_t capacity_{0};
            std::shared_ptr<void> ext_;
        public:
            Packet(int32_t size)
            :capacity_(size)
            {

            }
            ~Packet() {};

            static PacketPtr NewPacket(int32_t size);

            bool IsVideo() const
            {
                return (type_&KPacketTypeVideo) == KPacketTypeVideo;
            }
            bool IsKeyFrame() const
            {
                return ((type_&KPacketTypeVideo) == KPacketTypeVideo)
                        &&(type_&KFrameTypeKeyFrame) ==KFrameTypeKeyFrame;        
                       
            }
            bool IsAudio()  const
            {
                return type_ == KPacketTypeAudio;
            }
            bool IsMeta() const
            {
                return type_ == KPacketTypeMeta;
            }
            bool IsMeta3() const
            {
                return type_ == KPacketTypeMeta3;
            }

            inline int32_t PacketSize() const
            {
                return size_;
            }
            inline int Space() const 
            {
                return capacity_ - size_;
            }
            inline void SetPacketSize(size_t len)
            {
                size_ =  len;
            }
            inline void UpdatePacketSize(size_t len)
            {
                size_ += len;
            }

            template<class T>
            inline std::shared_ptr<T> Ext() const
            {
                return std::static_pointer_cast<T>(ext_);
            }
            inline void SetExt(const std::shared_ptr<void> &ext)
            {
                ext_ = ext;
            }

            void SetIndex(int32_t index)
            {
                index_ = index;
            }
            int32_t Index() const 
            {
                return index_;
            }
            void SetPacketType(int32_t type)
            {
                type_ = type;
            }
            int32_t PacketType() const 
            {
                return type_;
            }
            void SetTimeStamp(uint64_t timestamp)
            {
                timestamp_ =  timestamp;
            }
            uint64_t TimeStamp() const 
            {
                return timestamp_;
            }
            inline char * Data()
            {
                return (char*)this+sizeof(Packet);
            } 
            
        };
  #pragma pack()   //这个类一编译完就用系统的对齐方式
    } 
    
    
} 

